﻿using System;
using System.Collections.Generic;
using System.IO.Compression;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Dotnet.Utils.Utility.Zip
{
    public class ZipHelper
    {
        /*
NuGet安装 System.IO.Compression.ZipFile 包  


处理zip存档及其文件条目的方法分布在三个类中：
    ZipFile：https://docs.microsoft.com/zh-cn/dotnet/api/system.io.compression.zipfile
    ZipArchive：https://docs.microsoft.com/zh-cn/dotnet/api/system.io.compression.ziparchive
    ZipArchiveEntry：https://docs.microsoft.com/zh-cn/dotnet/api/system.io.compression.ziparchiveentry

        - ZipFile.CreateFromDirectory：从目录创建zip存档。
        - ZipFile.ExtractToDirectory：将zip存档的内容提取到目录中。
        - ZipArchive.CreateEntry：将新文件添加到现有的zip存档中。
        - ZipArchive.GetEntry：从zip存档中检索文件。
        - ZipArchive.Entries：从zip存档中检索所有文件。
        - ZipArchiveEntry.Open：将流打开到zip存档中包含的单个文件。
        - ZipArchiveEntry.Delete：从zip存档中删除文件。
         */



        /// <summary>
        /// 文件夹压缩成ZIP
        /// </summary>
        /// <param name="zipPath">压缩文件路径</param>
        /// <param name="zipFolderPath">被压缩文件夹目录</param>
        public static void CompressFolderZip(string zipPath, string zipFolderPath)
        {
            ZipFile.CreateFromDirectory(zipFolderPath, zipPath);
        }

        /// <summary>
        /// 文件压缩成ZIP
        /// </summary>
        /// <param name="filePath">被压缩文件路径</param>
        public static void CompressFileZip(string filePath)
        {
            string zipPath = string.Concat(Path.Combine(Path.GetDirectoryName(filePath), Path.GetFileNameWithoutExtension(filePath)), ".zip");
            CompressFileZip(zipPath, filePath);
        }

        /// <summary>
        /// 文件压缩成ZIP
        /// </summary>
        /// <param name="zipPath">压缩文件路径</param>
        /// <param name="filePath">被压缩文件路径</param>
        public static void CompressFileZip(string zipPath, string filePath)
        {
            using (FileStream zipFileToOpen = new FileStream(zipPath, FileMode.OpenOrCreate))
            {
                using (ZipArchive archive = new ZipArchive(zipFileToOpen, ZipArchiveMode.Update))
                {
                    archive.CreateEntryFromFile(filePath, Path.GetFileName(filePath));
                }
            }
        }

        /// <summary>
        /// 解压文件到指定目录
        /// </summary>
        /// <param name="zipPath">压缩文件路径</param>
        /// <param name="upZipDirPath">解压缩文件夹目录</param>
        public static void UnZip(string zipPath, string upZipDirPath = "")
        {
            if (string.IsNullOrEmpty(upZipDirPath))
            {
                upZipDirPath = Path.Combine(Path.GetDirectoryName(zipPath), Path.GetFileNameWithoutExtension(zipPath));
            }

            if (!Directory.Exists(upZipDirPath)) Directory.CreateDirectory(upZipDirPath);
            ZipFile.ExtractToDirectory(zipPath, upZipDirPath, true);
        }

        /// <summary>
        /// 获取Zip内部文件流
        /// </summary>
        /// <param name="zipPath">压缩文件Zip路径</param>
        /// <param name="fileName">压缩内部文件路径名称</param>
        /// <returns></returns>

        public static Stream GetZipFileStream(string zipPath, string fileName)
        {
            using (var zipFileToOpen = File.OpenRead(zipPath))
            {
                using (ZipArchive archive = new ZipArchive(zipFileToOpen, ZipArchiveMode.Read))
                {
                    using (var r = archive.GetEntry(fileName).Open())
                    {
                        return r;
                    }
                }
            }
        }

        /// <summary>
        /// 获取Zip内部所有文件名称
        /// </summary>
        /// <param name="zipPath">压缩文件Zip路径</param>
        /// <returns></returns>
        public static IEnumerable<string> GetZipFilesName(string zipPath)
        {
            using var file = File.OpenRead(zipPath);
            using var zip = new ZipArchive(file, ZipArchiveMode.Read);
            return zip.Entries.Select(z => z.FullName);

            ////遍历获取文件流
            //foreach (var entry in zip.Entries)
            //{
            //    using var stream = entry.Open();
            //}
        }
    }
}